package engine.loaders
{
	import engine.core.*;
	
	import flash.display.*;
	import flash.events.*;
	import flash.media.*;
	import flash.net.*;
	import flash.system.*;
	import flash.utils.*;
	
	public class RxLoader
	{
		private var m_url:String;
		private var m_blob:String;
		private var m_type:int;
		private var m_size:int;
		private var m_source:int;
		private var m_urlRequest:URLRequest;
		private var m_urlLoader:URLLoader;
		private var m_loader:Loader;
		private var m_sound:Sound;
		private var m_dispatcher:EventDispatcher;
		private var m_completionCallbacks:Vector.<RxLoaderCallback>;
		private var m_retries:int;
		private var m_loadedText:String;
		private var m_loadedData:ByteArray;
		private var m_loadedBitmap:Bitmap;
		private var m_loadedMovieClip:MovieClip;
		private var m_decompressImage:Boolean;
		private var m_suppressIOError:Boolean;
		private var m_callbacksExecuted:Boolean;
		private var m_startTime:Number;
		private var m_endTime:Number;
		private var m_startFrame:int;
		private var m_endFrame:int;
		private static var s_assetPath:String;
		private static const NUM_RETRIES:int = 3;
		private static const SOUND_TIME:int = 5000;
		public static const TYPE_TEXT:int = 0;
		public static const TYPE_DATA:int = 1;
		public static const TYPE_IMAGE:int = 2;
		public static const TYPE_MOVIECLIP:int = 3;
		public static const TYPE_SOUND:int = 4;
		public static const SOURCE_LOCAL:int = 0;
		public static const SOURCE_REMOTE:int = 1;
		
		public function RxLoader(url:String, type:int)
		{
			this.m_url = RxUtilities.NormalizeURL(url);			
			this.m_type = type;
			this.m_size = 0;
			this.m_source = RxLoader.SOURCE_LOCAL;
			this.m_retries = RxLoader.NUM_RETRIES;
			this.m_suppressIOError = false;
			this.m_decompressImage = true;
			this.m_completionCallbacks = new Vector.<RxLoaderCallback>;
			switch(this.m_type)
			{
				case TYPE_TEXT:
				{
					this.m_urlLoader = new URLLoader();
					this.m_urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
					this.m_dispatcher = this.m_urlLoader;
					break;
				}
				case TYPE_DATA:
				case TYPE_MOVIECLIP:
				{
					this.m_urlLoader = new URLLoader();
					this.m_urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
					this.m_dispatcher = this.m_urlLoader;
					break;
				}
				case TYPE_IMAGE:
				{
					this.m_loader = new Loader();
					this.m_dispatcher = this.m_loader.contentLoaderInfo;
					break;
				}
				case TYPE_SOUND:
				{
					this.m_sound = new Sound();
					this.m_dispatcher = this.m_sound;
					break;
				}
				default:
				{
					break;
				}
			}
			this.m_dispatcher.addEventListener(IOErrorEvent.IO_ERROR, this.OnIOError);
			this.m_dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.OnSecurityError);
			this.m_dispatcher.addEventListener(Event.COMPLETE, this.OnComplete);
		}
		
		private function OnComplete(e:Event) : void
		{
			trace("OnComplete url:", this.m_url);
			var swfContext:LoaderContext;
			var swfLoader:Loader;
			var event:* = e;
			this.m_endTime = getTimer();
			this.m_endFrame = RxTick.frame;
			this.RemoveListeners();
			switch(this.m_type)
			{
				case TYPE_TEXT:
				{
					this.m_size = event.target.bytesTotal;
					this.m_loadedText = event.target.data;
					this.m_urlLoader = null;
					this.m_dispatcher = null;
					this.ExecuteCompletionCallbacks(true);
					break;
				}
				case TYPE_DATA:
				{
					this.m_size = event.target.bytesTotal;
					this.m_loadedData = event.target.data;
					this.m_urlLoader = null;
					this.m_dispatcher = null;
					this.ExecuteCompletionCallbacks(true);
					break;
				}
				case TYPE_IMAGE:
				{
					this.m_size = event.target.bytesLoaded;
					this.m_loadedBitmap = event.target.content;
					this.m_loader = null;
					this.m_dispatcher = null;
					this.ExecuteCompletionCallbacks(true);
					break;
				}
				case TYPE_MOVIECLIP:
				{
					this.m_urlLoader = null;
					this.m_dispatcher = null;
					swfContext = new LoaderContext();
					swfContext.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
					swfLoader = new Loader();
					swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (event:Event) : void
					{
						(event.target as EventDispatcher).removeEventListener(event.type, arguments.callee);
						m_size = event.target.bytesLoaded;
						m_loadedMovieClip = event.target.content;
						ExecuteCompletionCallbacks(true);
			
					}
					);
					swfLoader.loadBytes(event.target.data, swfContext);
					break;
				}
				case TYPE_SOUND:
				{
					this.m_size = event.target.bytesLoaded;
					this.m_dispatcher = null;
					this.ExecuteCompletionCallbacks(true);
					break;
				}
				default:
				{
					break;
					break;
				}
			}
		}
		
		private function OnIOError(event:IOErrorEvent) : void
		{
			trace("OnIOError url:", this.m_url);
			/*
			if (this.m_retries != 0)
			{
				this.m_retries--;
				this.Load();
			}
			else
			{
				if (this.m_suppressIOError == false)
				{
					RxLog.Error("I/O Error while loading file " + this.m_url);
				}
				this.RemoveListeners();
				this.ExecuteCompletionCallbacks(false);
			}*/
			
			this.RemoveListeners();
			this.ExecuteCompletionCallbacks(false);
		}
		
		private function OnSecurityError(event:SecurityErrorEvent) : void
		{
			RxLog.Error("Security Error while loading file " + this.m_url);
			this.RemoveListeners();
			this.ExecuteCompletionCallbacks(false);
			trace("OnSecurityError url:", this.m_url);
		}
		
		private function ExecuteCompletionCallbacks(bol:Boolean) : void
		{
			var callback:RxLoaderCallback = null;
			if (!this.m_callbacksExecuted)
			{
				for each (callback in this.m_completionCallbacks)
				{
					
					callback.m_result = bol;
					callback.m_loader = this;
					callback.m_startTime = this.m_startTime;
					callback.m_endTime = this.m_endTime;
					callback.m_startFrame = this.m_startFrame;
					callback.m_endFrame = this.m_endFrame;
					callback.m_function(callback);
				}
				
				this.m_callbacksExecuted = true;
			}
		}
		
		private function RemoveListeners() : void
		{
			if (this.m_dispatcher != null)
			{
				this.m_dispatcher.removeEventListener(IOErrorEvent.IO_ERROR, this.OnIOError);
				this.m_dispatcher.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.OnSecurityError);
				this.m_dispatcher.removeEventListener(Event.COMPLETE, this.OnComplete);
				this.m_dispatcher = null;
			}
		}
		
		public function Load() : void
		{
			var context:LoaderContext;
			var soundContext:SoundLoaderContext;
			this.m_completionCallbacks.fixed = true;
			if (this.m_url == null || this.m_url == "")
			{
				if (this.m_suppressIOError == false)
				{
					RxLog.Error("RxLoader.Load(): Invalid URL \'" + this.m_url + "\'");
				}
				this.ExecuteCompletionCallbacks(false);
	
			}
			switch(this.m_source)
			{
				case RxLoader.SOURCE_LOCAL:
				{
					this.m_blob = RxManifest.GetBlob(this.m_url);
					if (this.m_blob != null)
					{
						this.m_urlRequest = new URLRequest(this.m_blob);
						this.m_source = RxLoader.SOURCE_REMOTE;
					}
					else
					{
						this.m_urlRequest = new URLRequest(s_assetPath + this.m_url.toLowerCase());
					}
					break;
				}
				case RxLoader.SOURCE_REMOTE:
				{
					this.m_urlRequest = new URLRequest(this.m_url);
					break;
				}
				default:
				{
					break;
				}
			}
			this.m_startTime = getTimer();
			this.m_startFrame = RxTick.frame;
			try
			{
				switch(this.m_type)
				{
					case TYPE_TEXT:
					case TYPE_DATA:
					case TYPE_MOVIECLIP:
					{
						this.m_urlLoader.load(this.m_urlRequest);
						
						trace("load url:", this.m_url);
						break;
					}
					case TYPE_IMAGE:
					{
						context = new LoaderContext();
						if (this.m_decompressImage)
						{
							context.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;
						}
						else
						{
							context.imageDecodingPolicy = ImageDecodingPolicy.ON_DEMAND;
						}
						this.m_loader.load(this.m_urlRequest, context);
						
						trace("load url:", this.m_url);
						break;
					}
					case TYPE_SOUND:
					{
						soundContext = new SoundLoaderContext(SOUND_TIME);
						this.m_sound.load(this.m_urlRequest, soundContext);
						
						trace("load url:", this.m_url);
						break;
					}
					default:
					{
						break;
						break;
					}
				}
			}
			catch (error:Error)
			{
				RxLog.Error("Exception on file load : " + m_url + " : " + error.message);
				ExecuteCompletionCallbacks(false);
			}
		}
		
		public static function GetAssetPath() : String
		{
			return s_assetPath;
		}
		
		public function AddCompletionCallback(param1:RxLoaderCallback) : void
		{
			this.m_completionCallbacks.push(param1);
		}
		
		public function SetSource(param1:int) : void
		{
			this.m_source = param1;
		}
		
		public function SuppressIOError(param1:Boolean) : void
		{
			this.m_suppressIOError = param1;
		}
		
		public function GetText() : String
		{
			return this.m_loadedText;
		}
		
		public static function Initialize(assetPath:String) : void
		{
			s_assetPath = assetPath;
		}
		
		public function Delete() : void
		{
			var _loc_1:RxLoaderCallback = null;
			this.Cancel();
			this.m_url = null;
			this.m_blob = null;
			for each (_loc_1 in this.m_completionCallbacks)
			{
				
				_loc_1.Delete();
			}
			this.m_completionCallbacks = null;
		}
		
		public function Cancel() : void
		{
			this.RemoveListeners();
			switch(this.m_type)
			{
				case TYPE_TEXT:
				{
					this.m_urlLoader = null;
					this.m_dispatcher = null;
					this.m_loadedText = null;
					break;
				}
				case TYPE_DATA:
				{
					this.m_urlLoader = null;
					this.m_dispatcher = null;
					this.m_loadedData = null;
					break;
				}
				case TYPE_IMAGE:
				{
					if (this.m_loader != null)
					{
						this.m_loader.unload();
						this.m_loader = null;
					}
					this.m_dispatcher = null;
					if (this.m_loadedBitmap != null)
					{
						this.m_loadedBitmap.bitmapData.dispose();
					}
					this.m_loadedBitmap = null;
					break;
				}
				case TYPE_MOVIECLIP:
				{
					this.m_urlLoader = null;
					this.m_dispatcher = null;
					this.m_loadedMovieClip = null;
					break;
				}
				case TYPE_SOUND:
				{
					this.m_sound = null;
					break;
				}
				default:
				{
					break;
					break;
				}
			}
			this.ExecuteCompletionCallbacks(false);
		}
		
		public function GetSizeInBytes() : int
		{
			return this.m_size;
		}
		
		public function GetMovieClip() : MovieClip
		{
			return this.m_loadedMovieClip;
		}
		
		public function GetData() : ByteArray
		{
			return this.m_loadedData;
		}
		
		public function GetBitmap() : Bitmap
		{
			return this.m_loadedBitmap;
		}
		public function DecompressImageOnLoad(param1:Boolean) : void
		{
			this.m_decompressImage = param1;
		}
		
		public function GetURL() : String
		{
			return this.m_url;
		}
		
		public function GetSound() : Sound
		{
			return this.m_sound;
		}
		
		public static function IsAssetPathLocal() : Boolean
		{
			var _loc_1:* = s_assetPath.indexOf("http");
			if (_loc_1 == 0)
			{
				return false;
			}
			return true;
		}
	}
}